package com.meta.nd.vo;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.meta.nd.util.NodeUtil;
import com.meta.nd.vo.json.NvDeserializer;
import com.meta.nd.vo.json.NvSerializer;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@JsonSerialize(using = NvSerializer.class)
@JsonDeserialize(using = NvDeserializer.class)

public class Nv {
	Nd nd;
	protected long id;
	protected String metaNdCode;
	protected String actualNdCode;
	protected Nv parent=null;
	protected long parentId = 0L;
	protected Map<String, Fv> fvs = new HashMap<String,Fv>();//key值为name
	protected Map<String, List<Nv> > childrenMap = new HashMap<String,List<Nv>> ();//这里的键值为name
	protected String operationFlag;
public Nv(Nd nd){
	this.nd = nd;
	this.metaNdCode=nd.getNdCode();
	this.actualNdCode=nd.getNdCode();
}
	public Long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public Long getParentId() {
		return parentId;
	}
	public void setParentId(long parentId) {
		this.parentId = parentId;
	}
	public String getActualNdCode() {
		return actualNdCode;
	}

	public void setActualNdCode(String actualNdCode) {
		this.actualNdCode = actualNdCode;
	}

	public Map<String, Fv> getFvs() {
		return fvs;
	}
	public void setFvs(Map<String, Fv> fvs) {
		this.fvs = fvs;
	}
	public void setFv(  Fv fv ) {
		this.fvs.put(fv.getName(), fv);
	}
	
	public Map<String, List<Nv>> getChildrenMap() {
		return childrenMap;
	}
	public void setChildrenMap(Map<String,List<Nv>> childrenMap) {
		this.childrenMap = childrenMap;
	}
	public Nv getParent() {
		return parent;
	}
	public void setParent(Nv parent) {
		this.parent = parent;
	}
	public String getMetaNdCode() {
		return metaNdCode;
	}
	public void setMetaNdCode(String code) {
		this.metaNdCode = code;
	}

	public String getOperationFlag() {
		return operationFlag;
	}
	public void setOperationFlag(String operationFlag) {
		this.operationFlag = operationFlag;
	}

	public Nv getRoot() {
		if (parent == null )
			return this;
		
		Nv tempRoot = parent;
		
		
		while (tempRoot != null && tempRoot.getParent() != null ) {
			tempRoot = tempRoot.getParent();
		}
		
		return tempRoot;
		
	}	
	
	public Nd getRootNd() {
		return this.nd.getRoot();
	}
	
	public Nd getNd() {
		return this.nd;
	}

	public void setNd(Nd nd){
		this.nd = nd;
	}
	
	public List<Nv> getChildNvs( String name ){
		return this.childrenMap.get(name);
	}
	
	public Nv getSingleChildNv (String name ) {
		List<Nv>  children = this.getChildNvs(name);
		if ( children == null  || children.size() == 0 )
			throw new RuntimeException("没有子孩子");
		else if (children.size() >1 )
			throw new RuntimeException("多于一个孩子");
		
		return children.get(0);
	}
	

	public List<Nv> getSingleChildren(  ) {
			
		if ( this.getNd().getChildren().size() == 0 )
			throw new RuntimeException("没有子孩子");
		else 		if ( this.getNd().getChildren().size() > 1 )
			throw new RuntimeException("多于一个孩子");
		else {
			Nd childNd = this.getNd().getSingleChildNd();
			List<Nv>  children = this.getChildNvs(childNd.getNdName());
			return children;
		}
		
	}
	
	
	
	public void setChildNv(String name, List<Nv> nvs ) {
		for ( Nv nv : nvs ) 
			nv.setParent(this);
		this.childrenMap.put(name, nvs);
		
	}
	
	public void setChildNv( String name, Nv nv ) {
		nv.setParent(this);
		List<Nv> nvs = new ArrayList<Nv>();
		nvs.add(nv);
		this.childrenMap.put(name, nvs);	
	}
	
	public void addChildNv ( String name, Nv nv ) {

		if ( this.childrenMap.get(name) == null ) {
			setChildNv( name, nv);
		}
		else {
			this.childrenMap.get(name).add(nv);
			nv.setParent(this);
		}
	}

	public void addChildNvs ( String name, List<Nv> nvs ) {
		if ( this.childrenMap.get(name) == null ) {
			setChildNv( name, nvs);
		}
		else {
			this.childrenMap.get(name).addAll(nvs);
			for( Nv nv : nvs )
				nv.setParent(this);
		}
	}


public void setFvByName(String name, Object value) {
	Fv fv = fvs.get(name);
	if ( fv == null )
		return;
	if ( value == null ) {
		fv.setValue(value);
		return;
	}
	String dataType = fv.getDataType();
	if ( NodeUtil.matchDataType(dataType, value) ) {
		fv.setValue(value);
	}else {
		throw new RuntimeException("无效的数据类型！");
	}
}
	
public void setIntFvByName(String name, Integer value) {
		setFvByName(name,value);
	}
	
public  int getRawIntByName( String name ) {
	Fv fv = this.fvs.get(name);
	if (fv != null )
		return fv.getRawInt();
	else
		return 0;
}
	

	
	public void setLongFvByName(String name, Long value) {
		setFvByName(name,value);
		
	}
	
	public  long getRawLongByName( String name ) {
		Fv fv = this.fvs.get(name);
		if (fv != null )
			return fv.getRawLong();
		else
			return 0L;
	}
	
	
	public void setDoubleFvByName(String name, double value) {
		setFvByName(name,value);
	}
	
	public  double getRawDoubleByName( String name ) {
		Fv  fv = this.fvs.get(name);
		if ( fv == null )
			return 0.0;
		else
			return fv.getRawDouble();
	}
	
	public void setStringFvByName(String name, String value) {
		setFvByName(name,value);
	}
	
	public void setBoolFvByName(String name, Boolean value) {
		setFvByName(name,value);
	}

	public List<String> getStringListByName( String name){
		Fv  fv = this.fvs.get(name);
		if ( fv == null )
			return  new ArrayList<>();
		else
			return fv.getRawStringList();
	}

	public void setStringListFvByName(String name, List<String> value) {
		setFvByName(name,value);
	}
	
	public  String getRawStringByName( String name ) {
		Fv fv = this.fvs.get(name);
		if (fv != null )
			return fv.getRawString();
		else
			return null;
	}
	
	public  Boolean getRawBoolByName( String name ) {
		Fv fv = this.fvs.get(name);
		if (fv != null )
			return fv.getRawBool();
		else
			return false;
	}
	
	
	public void setDateFvByName(String name, Date value) {
		setFvByName(name,value);
	}
	
	public  Date getRawDateByName( String name ) {
		Fv fv = this.fvs.get(name);
		if (fv != null )
			return fv.getRawDate();
		else
			return null;
	}
	
	public Fv getFvByName(String name) {
		return this.getFvs().get(name);
	}

	@JsonIgnore
	public List<Nv> getSingleNvs(){
		if ( this.getChildrenMap().size() > 1 ){
			throw new RuntimeException("存在多个孩子节点");
		}
		else if (this.getChildrenMap().size() == 0){
			throw new RuntimeException("不存在孩子节点！");
		}
		else {
			String key = this.childrenMap.keySet().iterator().next();
			return this.getChildrenMap().get(key);
		}
	}

	@JsonIgnore
	public Object getValue(String fdName){
		return this.fvs.get(fdName).getValue();
	}

	@JsonIgnore
	public boolean isIdNull(){
		if (this.id <= 0 )
			return true;
		else
			return false;
	}
}
